import React, { FC, memo, useEffect, useRef, useState } from "react";
import {
  BarControl,
  BarOperator,
  BarPlayInfo,
  PlayerBarWrapper
} from "@/views/player/app-player-bar/style";
import { Link } from "react-router-dom";
import { message, Slider } from "antd";
import { useAppDispatch, useAppSelector } from "@/store";
import {
  changeLyricIndexAction,
  changeMusicAction,
  changePlayModeAction,
  fetchCurrentSongAction
} from "@/views/player/store/player";
import { getSongPlayUrl } from "@/utils/handle-player";
import { shallowEqual } from "react-redux";
import { formatTime, getImageSize } from "@/utils/format";

interface IProps {
  children?: React.ReactNode;
}

const AppPlayerBar: FC<IProps> = (props) => {
  const [isPlaying, setIsPlaying] = useState(false);
  // 总时间
  const [duration, setDuration] = useState(0);
  // 当前时间
  const [currentTime, setCurrentTime] = useState(0);
  // 当前时间 / 总时间 的百分比
  const [progress, setProgress] = useState(0);
  // 是否正在进行进度条拖拽
  const [isSliding, setIsSliding] = useState(false);
  const audioRef = useRef<HTMLAudioElement>(null);
  const { currentSong, lyrics, lyricIndex, playMode } = useAppSelector(
    (state) => ({
      currentSong: state.player.currentSong,
      lyrics: state.player.lyrics,
      lyricIndex: state.player.lyricIndex,
      playMode: state.player.playMode
    }),
    shallowEqual
  );
  const dispatch = useAppDispatch();

  useEffect(() => {
    async function fetchCurrentSong() {
      await dispatch(fetchCurrentSongAction(2638631174));
    }

    fetchCurrentSong();
  }, []);

  useEffect(() => {
    // 1. 播放音乐
    if (audioRef.current) {
      audioRef.current.src = getSongPlayUrl(currentSong.id);
    }

    audioRef.current
      ?.play()
      .then(() => {
        setIsPlaying(true);
        console.log("歌曲播放成功");
      })
      .catch((err) => {
        setIsPlaying(false);
        console.log("歌曲播放失败:", err);
      });

    // 2.获取音乐的总时长
    setDuration(currentSong.dt);
  }, [currentSong]);

  /**
   * 播放歌曲
   */
  function handlePlayBtnClick() {
    // 1.控制播放器的播放/暂停
    isPlaying
      ? audioRef.current?.pause()
      : audioRef.current?.play().catch(() => setIsPlaying(false));
    // 2.改变isPlaying的状态
    setIsPlaying(!isPlaying);
  }

  /**
   * 切换歌曲
   * @param isNext 是否下一首
   */
  function handleChangeMusic(isNext = true) {
    dispatch(changeMusicAction(isNext) as any);
  }

  /**
   * 当歌曲播放完成，自动切换
   */
  function handleTimeEnded() {
    if (playMode === 2) {
      // 单曲循环
      if (audioRef.current) {
        audioRef.current.currentTime = 0;
        audioRef.current.play();
      }
    } else {
      handleChangeMusic(true);
    }
  }

  /**
   * 歌曲播放进度的更新
   */
  const handleTimeUpdate = () => {
    // 1. 获取当前播放时间
    const currentTime = audioRef.current!.currentTime * 1000;
    // console.log("=>(index.tsx:72) currentTime", currentTime);
    // 没有拖拽的时候才可以设置进度
    if (!isSliding) {
      // 2. 计算当前歌曲进度
      const currentProgress = (currentTime / duration) * 100;
      setCurrentTime(currentTime);
      setProgress(currentProgress);
    }
    // 3. 根据当前的时间匹配对应的歌词
    // index 为目前所展示的歌词下标，存在一个问题，最后一句歌词匹配不上
    // let index = -1
    let index = lyrics.length - 1; // 为了解决最后一句歌词问题，默认赋值最后一句
    for (let i = 0; i < lyrics.length; i++) {
      const lyric = lyrics[i];
      if (lyric.time > currentTime) {
        index = i - 1;
        break;
      }
    }
    // 4. 匹配上歌词 保存该歌词对应的 index
    if (lyricIndex === index || index === -1) {
      // 说明匹配歌词相等，不需要重复展示（setter 歌词）
      return;
    }
    dispatch(changeLyricIndexAction(index));
    // 5. 展示对应歌词
    message.open({
      content: lyrics[index]?.text,
      key: "lyric",
      duration: 0
    });
  };
  /**
   * 点击切换歌曲进度条
   */
  const handleSliderChanged = (value: number) => {
    // todo 未解决 获取的 value 总是 currentTime 而不是 鼠标点击的 time
    //  必须要 changing 和 changed 配合使用？？？？？？
    // handleSliderChanging 可能完全可以解决 onChangeComplete 的问题
    // console.log(value);
    // 1. 获取点击位置的时间
    const currentTime = (value / 100) * duration;
    // 2. 设置 audio 的当前时间
    audioRef.current!.currentTime = currentTime / 1000;
    // 3. currentTime / progress
    setCurrentTime(currentTime);
    setIsSliding(false);
  };

  /**
   * 拖拽切换歌曲进度条
   * @param value
   */
  const handleSliderChanging = (value: number) => {
    // console.log(value);
    // 0. 目前处于拖拽状态
    setIsSliding(true);
    // 1. 设置 progress
    setProgress(value);
    // 2. 设置当前播放时间
    const currentTime = (value / 100) * duration;
    setCurrentTime(currentTime);
  };

  /**
   * 切换播放模式
   */
  const handleChangeMode = () => {
    let newPlayMode = playMode + 1;
    if (newPlayMode > 2) newPlayMode = 0;
    dispatch(changePlayModeAction(newPlayMode));
  };

  return (
    <PlayerBarWrapper className="sprite_playbar">
      <div className="content wrap-v2">
        <BarControl $isPlaying={isPlaying}>
          <button
            className="btn sprite_playbar prev"
            onClick={() => handleChangeMusic(false)}
          ></button>
          <button
            className="btn sprite_playbar play"
            onClick={handlePlayBtnClick}
          ></button>
          <button
            className="btn sprite_playbar next"
            onClick={() => handleChangeMusic(true)}
          ></button>
        </BarControl>
        <BarPlayInfo>
          <Link to="/player">
            <img
              className="image"
              src={getImageSize(currentSong?.al?.picUrl, 50)}
              alt=""
            />
          </Link>
          <div className="info">
            <div className="song">
              <span className="song-name">{currentSong?.name}</span>
              <span className="singer-name">{currentSong?.ar?.[0]?.name}</span>
            </div>
            <div className="progress">
              <Slider
                step={0.5}
                value={progress}
                tooltip={{ formatter: null }}
                onChangeComplete={handleSliderChanged}
                onChange={handleSliderChanging}
              ></Slider>
              <div className="time">
                <span className="current">{formatTime(currentTime)}</span>
                <span className="divider">/</span>
                <span className="duration">{formatTime(duration)}</span>
              </div>
            </div>
          </div>
        </BarPlayInfo>
        <BarOperator $playMode={playMode}>
          <div className="left">
            <button className="btn pip"></button>
            <button className="btn sprite_playbar favor"></button>
            <button className="btn sprite_playbar share"></button>
          </div>
          <div className="right">
            <button className="btn sprite_playbar volume"></button>
            <button
              className="btn sprite_playbar loop"
              onClick={handleChangeMode}
            ></button>
            <button className="btn sprite_playbar playlist"></button>
          </div>
        </BarOperator>
      </div>
      <audio
        ref={audioRef}
        onTimeUpdate={handleTimeUpdate}
        onEnded={handleTimeEnded}
      />
    </PlayerBarWrapper>
  );
};

export default memo(AppPlayerBar);
